package com.terrier.net
{
    import com.terrier.math.bigInteger.BigInteger;
    import com.terrier.utils.WxStringUtility;
    
    import flash.utils.ByteArray;
    import flash.utils.Endian;

    public class WxNetPacket extends ByteArray
    {
        private static var _defaultEndian:String = Endian.LITTLE_ENDIAN;

        public static function get defaultEndian():String
        {
            return _defaultEndian;
        }

        public static function set defaultEndian(value:String):void
        {
            _defaultEndian = value;
        }

        private var _id:uint;

        public function WxNetPacket(id:uint = 0)
        {
            super();
            _id = id;
            endian = defaultEndian;
        }

        public function get id():uint
        {
            return _id;
        }

        public function set id(value:uint):void
        {
            _id = value;
        }

        public function clone():WxNetPacket
        {
            var data:WxNetPacket = new WxNetPacket(id);
            data.writeBytes(this);
            data.position = 0;
            return data;
        }

        override public function toString():String
        {
            var data:WxNetPacket = clone();
            var str:String = "0x";
            while (data.bytesAvailable > 0)
            {
                var byte:String = data.readUnsignedByte().toString(16);
                str += WxStringUtility.toFixed(byte, 2, "0");
            }
            return str;
        }

        /**
         * 读取BigEndian字节序的字节数组
         * @param len 字节数
         * @return
         */
        public function readBigEndianBytes(len:int):ByteArray
        {
            var bytes:ByteArray = new ByteArray();
            bytes.endian = Endian.BIG_ENDIAN;
            bytes.length = len;
            var i:int = 0;
            if (Endian.LITTLE_ENDIAN == endian)
            {
                for (i = len - 1; i >= 0; --i)
                {
                    bytes[i] = readUnsignedByte();
                }
            }
            else
            {
                for (i = 0; i < len; ++i)
                {
                    bytes[i] = readUnsignedByte();
                }
            }
            return bytes;
        }

        /**
         * 写入BigEndian字节序的字节数组
         * @param value
         */
        public function writeBigEndianBytes(bytes:ByteArray):void
        {
            var i:int = 0;
            var len:int = bytes.length;
            if (Endian.LITTLE_ENDIAN == endian)
            {
                for (i = len - 1; i >= 0; --i)
                {
                    writeByte(bytes[i]);
                }
            }
            else
            {
                for (i = 0; i < len; ++i)
                {
                    writeByte(bytes[i]);
                }
            }
        }

        /**
         * 读取无符号的64位整型数
         * @return
         */
        public function readUnsignedInt64():BigInteger
        {
            var bytes:ByteArray = readBigEndianBytes(8);
            var bigInt:BigInteger = new BigInteger(bytes);
            return bigInt;
        }

        /**
         * 写入无符号的64位整型数
         * @param bigInt
         */
        public function writeUnsignedInt64(bigInt:BigInteger):void
        {
            var srcBytes:ByteArray = bigInt.toByteArray();
            var bytes:ByteArray = new ByteArray();
            bytes.length = 8;
            for (var i:int = 0; i < 8; ++i)
            {
                var index:int = bytes.length - 1 - i;
                var srcIndex:int = srcBytes.length - 1 - i;
                if (srcIndex < 0)
                {
                    break;
                }
                bytes[index] = srcBytes[srcIndex];
            }
            writeBigEndianBytes(bytes);
        }

        public function readCharArray(length:int):String
        {
            var str:String = "";
            var i:int = 0;
            for (i = 0; i < length; ++i)
            {
                var charCode:int = readUnsignedByte();
                if (charCode == 0)
                {
                    break;
                }
                str += String.fromCharCode(charCode);
            }
            for (++i; i < length; ++i)
            {
                readUnsignedByte();
            }
            return str;
        }

        public function writeCharArray(str:String, length:int):void
        {
            for (var i:int = 0; i < length; ++i)
            {
                if (i < str.length)
                {
                    writeByte(str.charCodeAt(i));
                }
                else
                {
                    writeByte(0);
                }
            }
        }

        public function readWideCharArray(length:int):String
        {
            var str:String = "";
            var i:int = 0;
            for (i = 0; i < length; ++i)
            {
                var charCode:int = readUnsignedShort();
                if (charCode == 0)
                {
                    break;
                }
                str += String.fromCharCode(charCode);
            }
            for (++i; i < length; ++i)
            {
                readUnsignedShort();
            }
            return str;
        }

        public function writeWideCharArray(str:String, length:int):void
        {
            for (var i:int = 0; i < length; ++i)
            {
                if (i < str.length)
                {
                    writeShort(str.charCodeAt(i));
                }
                else
                {
                    writeShort(0);
                }
            }
        }

        public function readByteUTF():String
        {
            var len:int = readUnsignedByte();
            return readUTFBytes(len);
        }
		
		public function writeByteUTF(str:String):void
        {
            if (str.length > 0xff)
            {
                str = str.substr(0, 0xff);
			}
			writeByte(str.length);
			writeUTFBytes(str);
		}
    }
}
